

package enterprise.jsf_jpa_war;

import enterprise.ent.Administradores;
import enterprise.ent.Country;
import enterprise.ent.Jugadores;
import enterprise.ent.Torneos;
import enterprise.ent.Usuarios;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpSession;
import javax.transaction.NotSupportedException;
import javax.transaction.Transactional;
import javax.transaction.UserTransaction;
import org.primefaces.event.FileUploadEvent;  
import org.primefaces.model.UploadedFile;  

/**
 * <p>A simple managed bean to mediate between the user
 * and the persistence layer.</p>
 * @author rlubke
 */
public class UserManager {
    
    /**
     * <p>The key for the session scoped attribute holding the
     * appropriate <code>Wuser</code> instance.</p>
     */
    public static final String USER_SESSION_KEY = "user";
    
    /**
     * <p>The <code>PersistenceContext</code>.</p>
     */
    @PersistenceContext 
    private EntityManager em;
    
    /**
     * <p>The transaction resource.</p>
     */
    @Resource 
    private UserTransaction utx;
    
    /**
     * <p>User properties.</p>
     */
    private String username;
    private String password;
    private String passwordv;
    private String email;
    private String genero;   
    private String foto;
    
    // -------------------------------------------------------------- Properties
    public String getEmail() {
        return email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    public String getFoto() {
        return foto;
    }
    
    public void setFoto(String foto) {
        this.foto = foto;
    }
    public String getGenero() {
        return genero;
    }
    
    public void setGenero(String genero) {
        this.genero = genero;
    }
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public String getPasswordv() {
        return passwordv;
    }
    
    public void setPasswordv(String passwordv) {
        this.passwordv = passwordv;
    }
    
    // ---------------------------------------------------------- Public Methods
    
    
    /**
     * <p>Validates the user.  If the user doesn't exist or the password
     * is incorrect, the appropriate message is added to the current
     * <code>FacesContext</code>.  If the user successfully authenticates,
     * navigate them to the page referenced by the outcome <code>app-main</code>.
     * </p>
     *
     * @return <code>app-main</code> if the user authenticates, otherwise
     *  returns <code>null</code>
     */
    public String validateUser() {   
        FacesContext context = FacesContext.getCurrentInstance();
        Usuarios user = getUser();
        System.out.println("Entra a validar usuario...");
        //System.out.println("GetUser::: " + user.getIdUsuario().toString());
        if (user != null) {
            if (!user.getUserPass().equals(password)) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                           context.getApplication().evaluateExpressionGet(context, "#{msg.login_incorrecto}", String.class)
                                           ,"Login error.");
                context.addMessage("logingrowl", message);
                
                
                
                return null;
            }
            
            //actualizamos el last login
            //user.setUserLastlogin(new Date());
            actualizarLastLogin(user.getIdUsuario());
            
            //establece los tipos de usuario: admin, jugador, usuario normal
            setTiposUsuario(user.getIdUsuario());
            
            context.getExternalContext().getSessionMap().put(USER_SESSION_KEY, user);
            
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
                    context.getApplication().evaluateExpressionGet(context, user.getUserUser() + "! #{msg.Bienvenido}", String.class)
                    ,null);
            context.addMessage("logingrowl", message);
            
            //pone la variable de sesion "SPAGINA" para que sea index
            Map sMap;
            sMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
            BeanMenu bm = (BeanMenu) sMap.get("beanMenu");
            bm.spagina = "index";
            
            return null;
            //return "app-main";
        } else {           
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "#{msg.login_incorrecto}", String.class)
                    ,null);
            context.addMessage("logingrowl", message);
            return null;
        }
    }
    
    /**
     * <p>Creates a new <code>Wuser</code>.  If the specified user name exists
     * or an error occurs when persisting the Wuser instance, enqueue a message
     * detailing the problem to the <code>FacesContext</code>.  If the 
     * user is created, move the user back to the login view.</p>
     *
     * @return <code>login</code> if the user is created, otherwise
     *  returns <code>null</code>
     */
    public String createUser() {
        FacesContext context = FacesContext.getCurrentInstance();
        Usuarios wuser = getUser();
        if (wuser == null) {
            if (!password.equals(passwordv)) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        context.getApplication().evaluateExpressionGet(context, "#{msg.pass_no_coincide}", String.class)
                        ,null);
                context.addMessage("creategrowl", message);
                return null;
            }
            wuser = new Usuarios();
            wuser.setUserUser(username);
            wuser.setUserPass(password);
            wuser.setUserEmail(email);
            wuser.setUserGenero(genero);
            wuser.setUserFecalta(new Date());
            wuser.setUserLastlogin(null);
            //se carga la foto por defecto, ya que la foto la determinara luego el usuario si quiere...
            wuser.setUserFoto("nofoto");
            try {
                utx.begin();
                em.persist(wuser);
                utx.commit();
                
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
                    context.getApplication().evaluateExpressionGet(context, "#{msg.cuenta_creada}!", String.class)
                    ,null);
                context.addMessage("creategrowl", message);
                
                
                //pone la variable de sesion "SPAGINA" para que sea index
                Map sMap;
                sMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
                BeanMenu bm = (BeanMenu) sMap.get("beanMenu");
                bm.spagina = "index";
                
                //return "app-main";
                return null;
            } catch (Exception e) {               
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                                        "Error creating user!",
                                                        "Unexpected error when creating your account.  Please contact the system Administrator");
                context.addMessage(null, message);
                Logger.getAnonymousLogger().log(Level.SEVERE,
                                                "Unable to create new user",
                                                e);
                return null;
            }
        } else {           
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                                    "Username '"
                                                      + username 
                                                      + "' already exists!  ",
                                                    "Please choose a different username.");
            context.addMessage(null, message);
            return null;
        }        
    }
    
    
    /**
     * <p>When invoked, it will invalidate the user's session
     * and move them to the login view.</p>
     *
     * @return <code>login</code>
     */
    public String logout() {
        HttpSession session = (HttpSession)
             FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        if (session != null) {
            session.invalidate();
        }
        //return "login";
        return "app-main";
        
    }
    
    // --------------------------------------------------------- Private Methods
    
    
    /**
     * <p>This will attempt to lookup a <code>Wuser</code> object
     * based on the provided user name.</p>
     *
     * @return a <code>Wuser</code> object associated with the current
     *  username, otherwise, if no <code>Wuser</code> can be found,
     *  returns <code>null</code>
     */
    private Usuarios getUser() {
        try {
            Usuarios user = (Usuarios)
            em.createNamedQuery("Usuarios.findByUserUser").
                    setParameter("userUser", username).getSingleResult();
            return user; 
        } catch (NoResultException nre) {
            return null;
        }
    }
    
    public String getNombreUser(Long iduser) {
        try {
            Usuarios user = (Usuarios)
            em.createNamedQuery("Usuarios.findByIdUsuario").
                    setParameter("idUsuario", iduser).getSingleResult();
            return user.getUserUser(); 
        } catch (NoResultException nre) {
            return null;
        }
    }

    public void setTiposUsuario(Long id) {
        Map sMap;
        sMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
        BeanMenu bm = (BeanMenu) sMap.get("beanMenu");
        try {
            Usuarios use = (Usuarios)
            em.createNamedQuery("Usuarios.findByIdUsuario").
                    setParameter("idUsuario", id).getSingleResult();
            bm.esUsuario = true;
        } catch (NoResultException nre) {
            bm.esUsuario = false;
        }
        try {
            Jugadores jug = (Jugadores)
            em.createNamedQuery("Jugadores.findByJugUser").
                    setParameter("jugUser", id).getSingleResult();
            bm.esJugador = true;
        } catch (NoResultException nre) {
            bm.esJugador = false;
        }
        try {
            Administradores adm = (Administradores)
            em.createNamedQuery("Administradores.findByAdminUser").
                    setParameter("adminUser", id).getSingleResult();
            bm.esAdmin = true;
        } catch (NoResultException nre) {
            bm.esAdmin = false;
        }
    }
    
    public void actualizarLastLogin(Long id) {
        FacesContext context = FacesContext.getCurrentInstance();
        try{
            utx.begin();
            Usuarios u = (Usuarios)
                em.createNamedQuery("Usuarios.findByIdUsuario").
                        setParameter("idUsuario", id).getSingleResult();
            u.setUserLastlogin(new Date());
            utx.commit();
        } catch (Exception e) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                                        "Error inesperado actualizando ultimo login!",
                                                        "Por favor contacta con el Administrador del sistema.");
            context.addMessage(null, message);
            Logger.getAnonymousLogger().log(Level.SEVERE,
                                            "Error inesperado actualizando ultimo login",
                                            e);
        }
    }
    

    public void handleFileUpload(FileUploadEvent event) {  
        this.foto = event.getFile().getFileName();
        
        FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");  
        FacesContext.getCurrentInstance().addMessage(null, msg);  
    }  
    
    
    /*
    private void setBDLastLogin() {
        try {
            String sSQL = "UPDATE usuarios SET user_lastlogin = :lastlogin WHERE id_usuario = " + getUser().getIdUsuario();
            em.createNativeQuery(sSQL).
                    setParameter("lastlogin", getUser().getUserLastlogin());
            //System.out.println(sSQL);
            //return user; 
        } catch (NoResultException nre) {
            //return null;
        }
    }*/
   
    public String checkUsuario(String userNombre) {
        Query query = em.createNamedQuery("Usuarios.findByUserUser");
        String paramLike = userNombre;
        query.setParameter("userUser", paramLike);
        List<Usuarios> tmpUsuarios = query.getResultList();
        
        if(tmpUsuarios.size() > 0){
            return "Nombre de usuario ya existente.";
        }
        if(userNombre.length() < 4){
            return "Minimo 4 carecteres.";
        }
        if(userNombre.length() > 24){
            return "Máximo 24 carecteres.";
        }       
        
        
        return "Ok!";
    }
    public void isUsernameValid(FacesContext ctx, UIComponent component, Object  value) throws ValidatorException
	{
                String userNombre = value.toString();
		Query query = em.createNamedQuery("Usuarios.findByUserUser");
                String paramLike = userNombre;
                query.setParameter("userUser", paramLike);
                List<Usuarios> tmpUsuarios = query.getResultList();
                FacesContext context = FacesContext.getCurrentInstance();
                
                if(tmpUsuarios.size() > 0){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "El usuario ya existe.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                    throw new ValidatorException(message);
                }
                
                if(userNombre.length() < 4){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Minimo 4 caracteres.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException(  context.getMessageList().get(context.getMessageList().size()-1));
                    throw new ValidatorException(message);
                }
                if(userNombre.length() > 24){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Maximo 24 caracteres.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                        throw new ValidatorException(message);
                }
                if(userNombre.contains(" ") ){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "No puede contener espacios.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                        throw new ValidatorException(message);
                } 

		
 
	}
}
